Skip to content

We try to maintain the same coding style as the rest of vRouter wherever we can, but still use conventions used by Windows Driver Kit wherever applicable (regarding variable names, P convention instead of * for specifying pointers to native Windows structures).

Below every rule, there is an example illustrating it with a code sample.

General

Styling

  • Use spaces, not tabs.
  • One indentation level is 4 spaces
  • Every line should end with a newline character ('\n')
  • Newlines commited into the remote repository should be Unix-like (newline character), avoid Windows-like newlines (carriage return; newline)
  • Avoid magic numbers, unless there is a very good reason.
  • Use define directives instead.
  • Statements with blocks (if, while, for, do...) should have the opening bracket in the same line
  • Statements with only one line instead of a whole block can skip brackets if it improves readability
  • Statements if/else should not skip brackets unless it can be done for both if, else and all eventual else ifs
if (condition)
    do_something();
else
    do_nothing();


if (condition) {
    do_something();
} else {
    i+= 1;
    do_nothing();
}


do {
    ASSERT(FALSE);
    nobody_uses_this_feature();
} while(condition);
  • If, for, while and similar statements should not be too long. This means, for example creating variables for parts of statement being checked
BOOLEAN usable = (value >= MIN_VALUE && value <= MAX_VALUE);
BOOLEAN safe = (state == STABLE);
if (usable && safe)
    do_something();

Files

  • Files in 'windows' directory are free to modify and do not have to be platform portable (they have to be Windows-compatible)
  • Other files need to be platform independant. This may be done in #ifdef manner, but more elegant solutions are preferable
  • For example callbacks
  • Function names should be: vr_filename.c or vr_filename.h ** Please note vrouter_mod.c is an exception to this
  • Files should be in directory: windows for Windows source files (.c extension) include for header files (.h extension) * dp-core for multiplatform source files (we don't forsee creating any) For header files, use guards to make sure there is no problem if they are included two or more times.
#ifndef __VR_DEFS_H__
#define __VR_DEFS_H__
// Some code
#endif
  • Use #ifdef, not #pragma once for guards

Naming

Functions

  • Name functions in snake case, names starting with vr_ or win_. Please note functions in vrouter_mod.c ATM don't follow this rule because of SxLibrary requirements. This will be changed when we get rid of it. vr_reinject_packet
  • vr_ variant should be used for multiplatform functions
  • win_ variant should be used for Windows-specific functions.
  • When defining function, place the type in one line and the rest of it in another line.
unsigned int
vr_reinject_packet(struct vr_packet *pkt, struct vr_forwarding_md *fmd)
  • When declaring functions, use the extern keyword and write everything in one line.
extern unsigned int vr_some_function();
  • It is preferential but not required to declare which parameters of a function are constant.
int
vr_function(const char* address)

Variables

  • We avoid constant literal variables. Instead, one should avoid magic numbers using #define directive. Const structs are OK.
#define MAX_SIZE 32
  • Global variables can be used whenever necessary, especially when the function being implemented will be called by some pre-existing dp-core code without supplying required arguments. However, it is preferential to avoid them. Static variables are lesser evil. Please check if a global variable can be replaced with a static one
  • Variables should be named using snake case.
LARGE_INTEGER current_gmt_time;
  • It is preferential but not required to declare constant variables as such
const unsigned int num_of_tries = input + 5;
  • If a value is known to be always positive, one should use unsigned variable. Same for bitfields.
unsigned int i = 5;
  • Variables should be initialized before reading them.

Types

  • Existing types should be used as-is
PNET_BUFFER_LIST nbl;
  • New types and types declared by us should use snake case and begin with vr_.
struct vr_struct {};
  • Do not typedef function, use struct as a part of the name
struct vr_router* router = vrouter_get(0);

Comments

  • Both block and line comments are allowed
int i = pointer->field; // Pointer cannot be null

/* TODO: Fix this */
  • Non-obvious logic should be commented
  • Do not leave commented out code unless there is a very good reason.
  • Platform-specific code
  • Use #ifdefs to specify code that should be compiled on only selected platforms
#ifdef __KERNEL__
  • Prefer #ifdef to #if defined unless more specific statement checking if required.
#if defined(_WINDOWS) || defined(__FreeBSD__)
  • Do not use compiler or linker specific features in code if they would break compatibility with other tools. For example, most #pragma statements.
#ifdef _WINDOWS
#pragma warning(disable : 4018) // Disable warning about signed/unsigned mismatch
#endif
  • Try not to modify existing dp-core code if possible, otherwise modify it:
  • Preferential: Creating additional callbacks (can be NULL or empty functions on Linux/FreeBSD)

Using #ifdefs

  • Try not to use os, compiler or linker specific features if possible
  • If there is already some code implemented using them, consider reimplementing a native Linux function using Windows libraries. This function should only be compiled on Windows as Linux-like systems will provide their own implementation. Either of these two options will work
  • Write it in a file that will only be included on Windows
#ifdef the implementation
If the body of a function will be completely different on Linux and Windows, write one function header and footer and #ifdef the rest of the body
void print(const char* a)
{
#ifdef _WINDOWS
DbgPrint(a);
#else
printf(a);
#endif
}
  • Windows-specific code should be properely ASSERTed. Use this function or ASSERTMSG to check your assumptions

Other points

  • If a possible data-race condition arises, find the smallest critical section and wrap it into a mutex, semaphore or a RW lock.
  • Functions should return: In Windows-specific code: NDIS_STATUS and all effects via pointers unless the function cannot fail In multiplatform code: regular return value if functions succeeds and -errno if the function fails